package io.netty.example.http.websocketx.common.util;

import java.io.*;

/**
 * @author fuguangli
 * @description 前沿类
 * @Create date:    2017/4/28
 */

public class ByteObjConvert {
    /*解决粘包问题：包头(4个字节:记录包体长度的数字)+包体*/
    //

    /**
     * 将消息体包装成byte[]
     *
     * @param msg
     * @return 包头(4个字节:记录包体长度的数字)+包体
     * @throws UnsupportedEncodingException
     */
    public static byte[] wrapMsg(String msg) throws UnsupportedEncodingException {
        byte[] body = msg.getBytes("utf-8");

        byte[] head = ByteNumberConverter.intToByteArray(body.length);

        System.out.println();

        byte[] total = new byte[head.length + body.length];
        System.arraycopy(head, 0, total, 0, head.length);
        System.arraycopy(body, 0, total, head.length, body.length);

        return total;

    }

    //

    /**
     * 将byte解析成消息体
     *
     * @param data 包头(4个字节:记录包体长度的数字)+包体
     * @return
     */
    public static String parseMsg(byte[] data) throws UnsupportedEncodingException {
        byte[] head = new byte[4];
        System.arraycopy(data, 0, head, 0, 4);
        int bodylen = ByteNumberConverter.byteArrayToInt(head);

        byte[] body = new byte[bodylen];
        System.arraycopy(data, 4, body, 0, bodylen);
        return new String(body, "utf-8");
    }


    /**
     * 获取一个包体的大小
     *
     * @param data
     * @return
     * @throws UnsupportedEncodingException
     */
    public static int parseMsgLength(byte[] data) throws UnsupportedEncodingException {
        byte[] head = new byte[4];
        System.arraycopy(data, 0, head, 0, 4);
        int bodylen = ByteNumberConverter.byteArrayToInt(head);

        return 4 + bodylen;
    }

    /**
     * 在原数据上提取一个包体
     *
     * @param data
     * @return res[0]:提取的部分   res[1]:剩余的部分
     * @throws UnsupportedEncodingException
     */
    public static byte[][] extractMsg(byte[] data) throws UnsupportedEncodingException {
        //头部
        byte[] head = new byte[4];
        System.arraycopy(data, 0, head, 0, 4);
        int bodylen = ByteNumberConverter.byteArrayToInt(head);

        //身体
        byte[] body = new byte[bodylen];
        System.arraycopy(data, 4, body, 0, bodylen);

        //头部+身体
        byte[] total = mergeByteArray(head,body);

        //源数据剩余部分
        byte[] surplus = new byte[data.length - total.length];
        System.arraycopy(data, total.length, surplus, 0, surplus.length);

        byte[][] res = new byte[2][];
        res[0]=total;
        res[1]=surplus;


        return res;
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        byte[] src = wrapMsg("qwe");
        byte[] src1 = wrapMsg("345");
        byte[] all = mergeByteArray(src,src1);
        extractMsg(all);

    }


    /**
     * 合并多个字节数组
     * @param data
     * @return
     */
    public static byte[] mergeByteArray(byte[]... data) {
        if (data.length == 0) {
            return null;
        }
        int len = 0;
        for (byte[] ba : data) {
            if (ba.length == 0) {
                continue;
            }
            len += ba.length;
        }

        byte[] res = new byte[len];
        int sum = 0;
        for (byte[] ba : data) {
            if(ba.length==0){
                continue;
            }
            System.arraycopy(ba,0,res,sum,ba.length);
            sum+=ba.length;
        }
        return res;
    }


    public static Object byteToObject(byte[] bytes) {
        Object obj = null;
        ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
        ObjectInputStream oi = null;
        try {
            oi = new ObjectInputStream(bi);
            obj = oi.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bi.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                oi.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return obj;
    }

    public static byte[] objectToByte(Object obj) {
        byte[] bytes = null;
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = null;
        try {
            oo = new ObjectOutputStream(bo);
            oo.writeObject(obj);
            bytes = bo.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bo.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                oo.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bytes;
    }
}
